/*
 *  Emotion Media Center
 *
 *  Copyright (C) 2009 Davide Andreoli <dave@gurumeditation.it>
 *
 *  License LGPL-2.1, see COPYING file at project folder.
 *
 */

#include <unistd.h>
#include <fcntl.h>

#include <lirc/lirc_client.h>

#include "emc.h"
//~ #include "enna_config.h"
#include "emc_input.h"
#include "emc_module.h"

#define EMC_MODULE_NAME "input_lirc"



static Ecore_Fd_Handler *lirc_fd_handler;
static struct lirc_config *lirc_config;

static const struct
{
   const char *keyname;
   emc_input input;
} emc_lircmap[] = {
   { "Left",         EMC_INPUT_LEFT        },
   { "Right",        EMC_INPUT_RIGHT       },
   { "Up",           EMC_INPUT_UP          },
   { "Down",         EMC_INPUT_DOWN        },
   { "Home",         EMC_INPUT_HOME        },
   { "Ok",           EMC_INPUT_OK          },
   { "Prev",         EMC_INPUT_PREV        },
   { "Next",         EMC_INPUT_NEXT        },

   { "Stop",         EMC_INPUT_STOP        },
   { "Play",         EMC_INPUT_PLAY        },
   { "Pause",        EMC_INPUT_PAUSE       },
   { "Forward",      EMC_INPUT_FORWARD     },
   { "Rewind",       EMC_INPUT_REWIND      },
   { "Exit",         EMC_INPUT_EXIT        },

   { "Quit",         EMC_INPUT_QUIT        },
   { "Menu",         EMC_INPUT_MENU        },

   { "VolumeUp",     EMC_INPUT_VOLUMEUP    },
   { "VolumeDown",   EMC_INPUT_VOLUMEDOWN  },
   { "VolumeMute",   EMC_INPUT_VOLUMEMUTE  },


   { "Fullscreen",   EMC_INPUT_FULLSCREEN  },

   { "0",            EMC_INPUT_KEY_0       },
   { "1",            EMC_INPUT_KEY_1       },
   { "2",            EMC_INPUT_KEY_2       },
   { "3",            EMC_INPUT_KEY_3       },
   { "4",            EMC_INPUT_KEY_4       },
   { "5",            EMC_INPUT_KEY_5       },
   { "6",            EMC_INPUT_KEY_6       },
   { "7",            EMC_INPUT_KEY_7       },
   { "8",            EMC_INPUT_KEY_8       },
   { "9",            EMC_INPUT_KEY_9       },

  /* { "a",            EMC_INPUT_KEY_A       },
   { "b",            EMC_INPUT_KEY_B       },
   { "c",            EMC_INPUT_KEY_C       },
   { "d",            EMC_INPUT_KEY_D       },
   { "e",            EMC_INPUT_KEY_E       },
   { "f",            EMC_INPUT_KEY_F       },
   { "g",            EMC_INPUT_KEY_G       },
   { "h",            EMC_INPUT_KEY_H       },
   { "i",            EMC_INPUT_KEY_I       },
   { "j",            EMC_INPUT_KEY_J       },
   { "k",            EMC_INPUT_KEY_K       },
   { "l",            EMC_INPUT_KEY_L       },
   { "m",            EMC_INPUT_KEY_M       },
   { "n",            EMC_INPUT_KEY_N       },
   { "o",            EMC_INPUT_KEY_O       },
   { "p",            EMC_INPUT_KEY_P       },
   { "q",            EMC_INPUT_KEY_Q       },
   { "r",            EMC_INPUT_KEY_R       },
   { "s",            EMC_INPUT_KEY_S       },
   { "t",            EMC_INPUT_KEY_T       },
   { "u",            EMC_INPUT_KEY_U       },
   { "v",            EMC_INPUT_KEY_V       },
   { "w",            EMC_INPUT_KEY_W       },
   { "x",            EMC_INPUT_KEY_X       },
   { "y",            EMC_INPUT_KEY_Y       },
   { "z",            EMC_INPUT_KEY_Z       },*/

   { NULL,           EMC_INPUT_UNKNOWN     }
};


static emc_input
_get_input_from_event(const char *ev)
{
   int i;

   for (i = 0; emc_lircmap[i].keyname; i++)
   {
      if (!strcmp(emc_lircmap[i].keyname, ev))
        return emc_lircmap[i].input;
   }

   WRN("Unrecognized lirc key: '%s'", ev);
   // TODO here we could print a list of recognized keys
   return EMC_INPUT_UNKNOWN;
}

static int _lirc_code_received(void *data, Ecore_Fd_Handler * fd_handler)
{
   char *code, *event;
   int ret = -1;

   while (lirc_nextcode(&code) == 0 && code != NULL)
   {
      while ((ret = lirc_code2char(lirc_config, code, &event)) == 0
              && event != NULL)
      {
         emc_input in;

         in = _get_input_from_event(event);
         if (in != EMC_INPUT_UNKNOWN)
            emc_input_event_emit(in);
      }
   }
   return 1;
}

/* Enna module interface */
void
module_init(Emc_Module *em)
{
   struct lirc_config *config;
   int fd;

   // initialize lirc
   if ((fd = lirc_init("enna", 1)) == -1) // TODO need to close this? or ecore_fd_hand_del is enought?
   {
      ERR("could not initialize LIRC support");
      return;
   }
   if (lirc_readconfig(NULL, &config, NULL) != 0)
   {
      lirc_deinit();
      ERR("could not find Lirc config file");
      return;
   }
   lirc_config = config;

   // connect to the lirc socket
   fcntl(fd, F_SETFL, O_NONBLOCK);
   fcntl(fd, F_SETFD, FD_CLOEXEC);
   lirc_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ,
                                         _lirc_code_received, NULL, NULL, NULL);
}

Eina_Bool
module_shutdown(Emc_Module *em)
{
   if (lirc_fd_handler)
   {
      lirc_freeconfig(lirc_config);
      ecore_main_fd_handler_del(lirc_fd_handler);
      lirc_deinit();
   }
   return EINA_TRUE;
}

Emc_Module_Api module_api =
{
   EMC_MODULE_API_VERSION,
   EMC_MODULE_NAME,
   "LIRC Remote",
   NULL,
   "Module to control enna from your remote",
   "bla bla bla<br><b>bla bla bla</b><br><br>bla.",
   {
      module_init,
      module_shutdown
   }
};
